<template>
  <view @click="showCity = !props.disabled?!showCity:false">
    <!-- #ifdef APP-NVUE -->
    <view :eventPenetrationEnabled="true">
      <slot></slot>
    </view>
    <!-- #endif -->
    <!-- #ifndef APP-NVUE -->
    <slot></slot>
    <!-- #endif -->
    <tm-drawer :disabbleScroll="true" :round="props.round" ref="drawer" :height="820" :closable="true"
      :overlayClick="aniover" @open="drawerOpen" @cancel="cancel" @ok="confirm" :show="showCity"
      @update:show="closeDrawer" title="请选择地区" ok-text="确认">
      <tm-picker-view v-if="showCity" ref="picker" :height="590" @end="aniover = true" @start="aniover = false"
        :value="_colIndex" @update:modelValue="_colIndex = $event" @update:model-str="_colStr = $event"
        :model-str="_colStr" :default-value="_colIndex" :columns="_data"></tm-picker-view>
      <tm-button label="确认选择" block :margin="[32, 12]" :color="props.color" :linear="props.linear"
        :linear-deep="props.linearDeep" @click="confirm" :round="props.btnRound"></tm-button>
      <view :style="{ height: win_bottom + 'px' }"></view>
    </tm-drawer>
  </view>
</template>
<script lang="ts" setup>
/**
 * 地区选择器
 * @description 这是弹出式，滑动地址选择器，另还一个按步选择地区的组件，见：tm-city-cascader
 * @example <tm-city-picker v-model:show="show" v-model="status" v-model:model-str="statusw"></tm-city-picker>
 */
import {
  PropType,
  inject,
  Ref,
  ref,
  watchEffect,
  getCurrentInstance,
  watch,
  toRaw,
  computed,
  nextTick,
  onMounted,
} from "vue";
import { custom_props } from "../../tool/lib/minxs";
import tmDrawer from "../tm-drawer/tm-drawer.vue";
import { childrenData } from "./interface";
import { provinceData } from "../../tool/static/province";
import { cityData } from "../../tool/static/city";
import { areaData } from "../../tool/static/area";
import tmPickerView from "../tm-picker-view/tm-picker-view.vue";
import TmSheet from "../tm-sheet/tm-sheet.vue";
import tmText from "../tm-text/tm-text.vue";
import tmButton from "../tm-button/tm-button.vue";
const proxy = getCurrentInstance()?.proxy ?? null;
const drawer = ref<InstanceType<typeof tmDrawer> | null>(null);
const picker = ref<InstanceType<typeof tmPickerView> | null>(null);

/**
 * 事件说明：
 * v-model:show 双向绑定显示和隐藏选择器
 * v-model 双向绑定以selectedModel为模式的值。一般用来给数据库后台用的。
 * v-model:model-str 单向输出地区名称，
 * 一般用来绑定在Input组件或者其它组件上用来展示当前选择的地址名称，
 * 但我们服务器可能有的是id或者index，所以你可以v-model绑定数据，用此v-model:model-str来显示数据。
 * confirm 点击了确认按钮时触发，返回当前选择数据。
 * cancel 取消或者点击遮罩关闭了选择器都将触发。
 */
const emits = defineEmits([
  "update:show",
  "update:modelValue",
  "update:modelStr",
  "confirm",
  "cancel",
]);
const props = defineProps({
  ...custom_props,
  followTheme: {
    type: [Boolean, String],
    default: true,
  },
  //v-model以selectedModel为索引的值结果。
  modelValue: {
    type: Array as PropType<Array<string | number>>,
    default: () => [],
  },
  //单向输出地区名称以/分割。不管selectedModel是以哪种索引选项，此处始终以地区名称输出显示。
  //可以使用v-model:modelStr，外部不可更改。
  modelStr: {
    type: String,
    default: "",
  },
  //v-model:show来双向绑定显示和隐藏选择器。
  show: {
    type: [Boolean],
    default: false,
  },
  //赋值和选值方式
  //name:名称模式赋值和选择
  //id:地区id模式赋值和选择
  //index:索引模式赋值和选择
  selectedModel: {
    type: String,
    default: "id",
  },
  /**
 * 城市选择的级别
 * province:省级别。
 * city:省，市
 * area:省，市，县/区.
 */
  cityLevel: {
    type: String,
    default: "area",
  },
  // 手动赋值城市数据
  city: {
    type: Array as PropType<Array<childrenData>>,
    default: () => [],
  },
  color: {
    type: String,
    default: "primary",
  },
  linear: {
    type: String,
    default: "",
  },
  linearDeep: {
    type: String,
    default: "light",
  },
  btnRound: {
    type: Number,
    default: 3,
  },
  round: {
    type: Number,
    default: 12,
  },
  /**禁用时，通过插槽点击时，不会触发显示本组件，适合表单 */
  disabled:{
    type:Boolean,
    default:false
  }
});
const showCity = ref(true);
const _cityData = computed(() => props.city);
const _colIndex: Ref<Array<number>> = ref([]);
const _data = ref(chiliFormatCity_area());
let tmid: any = NaN;
const _colStr = ref("");
const aniover = ref(true);
const sysinfo = inject("tmuiSysInfo", {
  bottom: 0,
  height: 750,
  width: uni.upx2px(750),
  top: 0,
  isCustomHeader: false,
  sysinfo: null,
});
let win_bottom = sysinfo.bottom;

watchEffect(() => {
  showCity.value = props.show;
});
watch(
  [() => props.city, () => props.modelValue],
  () => {
    _data.value = chiliFormatCity_area();
    clearTimeout(tmid);
    tmid = setTimeout(function () {
      getIndexBymodel(_data.value, props.selectedModel, 0, props.modelValue);
      defaultModerStrGet();
    }, 500);
  },
  { deep: true }
);
function closeDrawer(e: boolean) {
  showCity.value = e;
  emits("update:show", showCity.value);
  getIndexBymodel(_data.value, "index", 0, toRaw(_colIndex.value));
}
// onMounted(()=>defaultModerStrGet())
function drawerOpen() {
  getIndexBymodel(_data.value, props.selectedModel, 0, props.modelValue);
}
//点击确认了地区。
function confirm() {
  if (!aniover.value) return;
  setVal();
  nextTick(() => {
    emits("confirm", props.modelValue);
    drawer.value?.close();
  });
}
function cancel() {
  if (!aniover.value) return;
  emits("cancel");
}
function setVal() {
  let val = [];
  if (props.selectedModel == "name") {
    val = _colStr.value.split("/") ?? [];
  } else if (props.selectedModel == "id") {
    val = getRouterId(_data.value, 0);
  } else {
    val = [..._colIndex.value];
  }

  emits("update:modelValue", val);
  emits("update:modelStr", _colStr.value);
}
function defaultModerStrGet() {
  clearTimeout(tmid);
  tmid = setTimeout(function () {
    if (_colIndex.value.length > 0) {
      let text = getRouterText(_data.value, 0);
      emits("update:modelStr", text.join("/"));
    }
  }, 200);
}
//模拟模型来返回index值
function getIndexBymodel(
  vdata: Array<childrenData> = [],
  model = "name",
  parentIndex = 0,
  value: Array<number | string> = []
): Array<number | string> {
  if (value.length == 0) return [];
  if (model == "name") {
    let item: any = vdata.filter((el) => value[parentIndex] == el["text"]);
    if (item.length == 0) {
      item = vdata[0];
      if (item) {
        value[parentIndex] = item["text"];
        _colIndex.value[parentIndex] = 0;
        if (item["children"]) {
          getIndexBymodel(item["children"], model, parentIndex + 1, value);
        }
      }
    } else {
      item = item[0];
      if (item) {
        _colIndex.value[parentIndex] = vdata.findIndex(
          (el) => el["text"] == item["text"]
        );
        if (item["children"]) {
          getIndexBymodel(item["children"], model, parentIndex + 1, value);
        }
      }
    }
  } else if (model == "id") {
    let item: any = vdata.filter((el) => value[parentIndex] == el["id"]);
    if (item.length == 0) {
      item = vdata[0];
      if (item) {
        value[parentIndex] = item["id"];
        _colIndex.value[parentIndex] = 0;
        if (item["children"]) {
          getIndexBymodel(item["children"], model, parentIndex + 1, value);
        }
      }
    } else {
      item = item[0];
      if (item) {
        _colIndex.value[parentIndex] = vdata.findIndex((el) => el["id"] == item["id"]);
        if (item["children"]) {
          getIndexBymodel(item["children"], model, parentIndex + 1, value);
        }
      }
    }
  }

  return _colIndex.value;
}
//返回 一个节点从父到子的路径id组。
function getRouterId(
  list: Array<childrenData> = [],
  parentIndex = 0,
 value: Array<number | string> = []
): Array<string | number> {
  let p: Array<string | number> = [];
  const _defalutValue = value.length==0?_colIndex.value:value;
  for (let i = 0; i < list.length; i++) {
    if (i == _defalutValue[parentIndex]) {
      p.push(list[i]["id"]);
      if (typeof _defalutValue[parentIndex] != "undefined") {
        let c = getRouterId(list[i]["children"], parentIndex + 1);
        p = [...p, ...c];
      }
      break;
    }
  }
  return p;
}
//返回 一个节点从父到子的路径text组。
function getRouterText(
  list: Array<childrenData> = [],
  parentIndex = 0
): Array<string | number> {
  let p: Array<string | number> = [];
  for (let i = 0; i < list.length; i++) {
    if (i == _colIndex.value[parentIndex]) {
      p.push(list[i]["text"]);
      if (typeof _colIndex.value[parentIndex] != "undefined") {
        let c = getRouterText(list[i]["children"], parentIndex + 1);
        p = [...p, ...c];
      }
      break;
    }
  }
  return p;
}
//格式化数据格式。
function chiliFormatCity_area() {
  let list: Array<childrenData> = [];

  if (_cityData.value.length > 0) {
    return _cityData.value;
  }

  provinceData.forEach((item: childrenData, index: number) => {
    list.push({
      id: item.value ?? "",
      text: String(item.label),
      children: [],
    });
  });
  if (props.cityLevel == "province") return list;
  cityData.forEach((item: childrenData, index: number) => {
    item.forEach((citem: childrenData, cindex: number) => {
      list[index]?.children.push({
        id: citem.value ?? "",
        text: citem.label ?? "",
        children: [],
      });
    });
  });
  if (props.cityLevel == "city") return list;
  list.forEach((item, index) => {
    item.children.forEach((citem, cindex: number) => {
      areaData[index][cindex].forEach((jitem) => {
        list[index]?.children[cindex]?.children.push({
          id: jitem.value ?? "",
          text: jitem.label ?? "",
        });
      });
    });
  });

  return list;
}

defineExpose({
  getList:chiliFormatCity_area,
  getIndexs:getIndexBymodel,
  getRouterId
})
</script>
